package org.nettyServer.server;

import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import com.alibaba.fastjson.JSON;
import io.netty.channel.*;
import lombok.extern.slf4j.Slf4j;
import org.nettyServer.command.CommandBase;
import org.nettyServer.connectionManage.ClientInfo;
import org.nettyServer.connectionManage.ConnectionManage;
import org.nettyServer.connectionManage.NotRegisterClientInfo;
import org.nettyServer.eunm.EMessageCode;
import org.nettyServer.messageHandle.MessageAdapter;
import org.nettyServer.messageHandle.MessageInfoRecord;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;


/**
 * 类描述:TCP客户端适配器
 */
@Slf4j
@Component
@ChannelHandler.Sharable
public class ServerHandler extends SimpleChannelInboundHandler {

    @Resource
    private MessageAdapter messageAdapter;


    /**
     * 长连接读取数据方法-处理业务逻辑
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress();
        String clientIP = insocket.getAddress().getHostAddress();
        String message = new String((byte[]) msg, StandardCharsets.UTF_8);
        log.info("客户端ip: {}, 收到消息: {}", clientIP, message);

        //获取对象
        CommandBase commandBase;
        try {
             commandBase= JSON.parseObject(message, CommandBase.class);
        }catch (Exception e){
            log.error("消息反序列化错误, 消息: {},异常{}", msg, e.getMessage());
            return;
        }
        if (commandBase == null){
            log.error("消息格式错误, 消息: {},异常{}", msg, "消息格式错误");
            return;
        }
        if (!EMessageCode.getCodeList().contains(commandBase.getCommandCode())){
            log.error("消息类型错误, 消息: {},异常{}", msg, "消息类型错误");
            return;
        }
        //消息处理
        messageHandle(commandBase, ctx.channel(),msg);
    }

    private void messageHandle(CommandBase commandBase, Channel channel, Object msg){
        if (EMessageCode.LOGIN.getCode().equals(commandBase.getCommandCode())){
            //具体消息处理
            messageAdapter.getAdapter(commandBase.getCommandCode()).handle(commandBase, channel);
        }else {
            //更新最后活动时间
            ClientInfo clientInfo = ConnectionManage.getClientInfo(channel);
            clientInfo.setLastActiveTime(System.currentTimeMillis());
            //具体消息处理
            messageAdapter.getAdapter(commandBase.getCommandCode()).handle(commandBase, channel);
        }
        //有效消息记录
        MessageInfoRecord.effectiveReceiveMessageInfoRecord(commandBase, channel, msg);
    }



    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, Object object)  {

    }


    /**
     * 通道连接时调用-处理业务逻辑
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress();
        String clientIP = insocket.getAddress().getHostAddress();
        log.info("客户端ip: {} ：通道已连接！", clientIP);
        NotRegisterClientInfo notRegisterClientInfo = NotRegisterClientInfo.builder()
                .ip(clientIP)
                .port(String.valueOf(insocket.getPort()))
                .channel(ctx.channel())
                .connectTime(System.currentTimeMillis())
                .build();
        ConnectionManage.addNotRegisterClientInfo(notRegisterClientInfo);
    }

    /**
     * 通道闲置触发-启动断线重连功能
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) {
        log.error("客户端连接断开");
        ConnectionManage.removeNotRegisterClientInfo(ctx.channel());
    }


    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        super.handlerAdded(ctx);
    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        super.handlerRemoved(ctx);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        log.error("客户端连接异常,{}", cause.getMessage());
        cause.printStackTrace();
    }

}
